package com.gsbelarus.gedemin.salary.ui;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import com.gsbelarus.gedemin.salary.entity.HorizontalBarData;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class HorizontalBarChart extends View {

    private List<HorizontalBarData> data;
    private Paint paint;
    private Type type = Type.STACKED_BAR_CHART;
    private float shadowRadius;

    public enum Type {
        SERIES_BAR_CHART, STACKED_BAR_CHART
    }

    public HorizontalBarChart(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public HorizontalBarChart(Context context) {
        super(context);
        init();
    }

    public HorizontalBarChart(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        paint = new Paint();
        setLayerType(LAYER_TYPE_SOFTWARE, paint);
        shadowRadius = convertDpToPixels(5f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (data == null || data.isEmpty()) return;

        switch (type) {
            case SERIES_BAR_CHART:
                drawSeriesBarChart(canvas);
                break;
            case STACKED_BAR_CHART:
                drawStackedBarChart(canvas);
                break;
        }
    }

    private void drawSeriesBarChart(Canvas canvas) {
        float top = 0;
        float bottom = getHeight();
        float left = getPaddingLeft();
        float right;

        long lumpSum = getLumpSum();

        for (HorizontalBarData d : data) {
            right = ((float) d.getSum() / (float) lumpSum) * (getRight() - getPaddingLeft() - getPaddingRight());

            paint.setColor(getContext().getResources().getColor(d.getColor()));
            canvas.drawRect(left, top + getPaddingTop(),
                    right + left, bottom - getPaddingBottom(), paint);

            left += right;
        }
    }

    private void drawStackedBarChart(Canvas canvas) {
        float top = 0;
        float bottom = getHeight();
        float left = 0;
        float right;

        long maxSum = data.get(0).getSum();

        for (HorizontalBarData d : data) {

            if (d.getSum() == maxSum)
                right = getRight();
            else
                right = ((float) d.getSum() / (float) maxSum) * getRight();

            paint.setColor(getContext().getResources().getColor(d.getColor()));
            paint.setShadowLayer(shadowRadius, 0, 0, Color.BLACK);
            canvas.drawRect(left + getPaddingLeft(),
                    top + getPaddingTop(),
                    right - getPaddingRight(),
                    bottom - getPaddingBottom(),
                    paint);
        }
    }

    private long getLumpSum() {
        long lumpSum = 0;
        for (HorizontalBarData d : data)
            lumpSum += d.getSum();
        return lumpSum;
    }

    private void sort() {
        Collections.sort(data, new Comparator<HorizontalBarData>() {
            @Override
            public int compare(HorizontalBarData lhs, HorizontalBarData rhs) {
                return ((Long) rhs.getSum()).compareTo(lhs.getSum());
            }
        });
    }

    public void animate(int durationMillis) {
        switch (type) {
            case STACKED_BAR_CHART:
                setPivotX(0);
                ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0f, 1f);
                scaleX.setDuration(durationMillis);
                scaleX.start();
                break;
            case SERIES_BAR_CHART:
                ObjectAnimator alpha = ObjectAnimator.ofFloat(this, "alpha", 0f, 1f);
                alpha.setDuration(durationMillis);
                alpha.start();
                break;
        }
    }

    private float convertDpToPixels(float dp) {
        return (dp * getContext().getResources().getDisplayMetrics().density);
    }

    public void setData(List<HorizontalBarData> data) {
        this.data = data;
        sort();
    }

    public List<HorizontalBarData> getData() {
        return data;
    }

    public void setType(Type type) {
        this.type = type;
    }

    public Type getType() {
        return type;
    }
}
